#include<iostream>
#include<string>
#include<stack>
#include<cstdio>
#include<vector>
#include<list>
#include<set>
#include<algorithm>
#include"QueryClass.h"

using namespace std;

int GetLevel(int c){
    switch(c){
	case '(':
	case ')':
	    return 0;
	case '~':
	case '|':
	case '&':
	    return 1;
	default:
	    return -1;
    }
}
string TextExist(){
    string Input="";
    cout<<"输入查找的文件：";
    cin>>Input;
    getchar();
    int open=1;
    fstream openText(Input,ios::in);
    if(!openText.is_open()){
	open=0;
    }else{
	openText.close();
    }
    while(!open){
	cout<<"文件不存在，打开失败！"<<endl;
	cout<<"请重新输入查找的文件：";
	cin>>Input;
	getchar();
	fstream openText(Input,ios::in);
	if(!openText.is_open()){
	    open=0;
	}else{
	    open=1;
	    openText.close();
	}
    }
    return Input;
}
//字符类型
int GetType(int c){
    if(c=='('||c==')'){
	return 0;
    }else if(c=='~'||c=='|'||c=='&'){
	return 1;
    }else{
	return 2;//非运算符
    }
}

class MultiQuery:virtual public AndQuery,virtual public OrQuery,virtual public DirectQuery,virtual public NotQuery{

    private:
    string FirstWord;
    string SecondWord;
    vector<int>MultiLine;
    vector<string>DealtWords;//对用户的输入表达式处理后保存
    set<string>ColorWords;//用于保存输入的字符串，在结果中有颜色打印
    
    
    public:
    MultiQuery(string s):TextClass(s){}
    ~MultiQuery(){
//	cout<<"delete MultiQuery"<<endl;
    }

    void SetDealtWords(vector<string>words){
	DealtWords.erase(DealtWords.begin(),DealtWords.end());
	DealtWords=words;
	for(auto it=words.begin();it!=words.end();it++){
	    ColorWords.insert(*it);
	}
//	cout<<"SetDealtWords"<<endl;
    }


    private:
    string getOneWord(vector<string>v,int position){
	string word;
	int i=0;
	for(auto it=v.begin();it!=v.end();i++,it++){
	    if(i==position){
		word=*it;
		break;
	    }
	}
	return word;

    }
    public:
    vector<int>getMultiLine(){
//	cout<<"getMultiLine"<<endl;
	return MultiLine;
    }
    void ShowDealtWords(){
	cout<<"DealtWords: ";
	for(auto it=DealtWords.begin();it!=DealtWords.end();it++){
	    cout<<*it<<" ";
	}
	cout<<endl;
    }
    void ShowResult(){
	cout<<"查询结果："<<endl;;
	if(MultiLine.empty()){
	    cout<<"    没有找到!"<<endl;
	    return;
	}

	//-------显示原文本---------
	/*
	map<int,string> s=getBTree().getLineText();
	map<int,string> e;
	for(auto it=MultiLine.begin();it!=MultiLine.end();it++){
	    auto tmp=s.find(*it);
	    if(tmp!=s.end()){
		e[*it]=tmp->second;
	    }
	}
	for(auto it=e.begin();it!=e.end();it++){
	    cout<<it->first<<"    ";
	    string colorword;
	    istringstream istream(it->second);
	    while(istream>>colorword){
		if(ColorWords.end()!=ColorWords.find(colorword)){
		    printf("\033[;31m%s\033[0m",colorword.c_str());
		}else{
		    printf("%s",colorword.c_str());
		}
		cout<<" ";
	    }
	    cout<<endl;
	}
	*/

	//------------显示分隔符号后文本--------------------
	map<int,vector<string>> sn=getBTree().getNewLineText();
	map<int,vector<string>>en;
	
	for(auto it=MultiLine.begin();it!=MultiLine.end();it++){
	    auto tmp=sn.find(*it);
	    if(tmp!=sn.end()){
		en[*it]=tmp->second;
	    }
	}
	for(auto it=en.begin();it!=en.end();it++){
	    cout<<it->first<<"    ";
	    for(auto in=it->second.begin();in!=it->second.end();in++){
		if(ColorWords.end()!=ColorWords.find(*in)){
		    printf("\033[;31m%s\033[0m",(*in).c_str());//红色输出
		}else{
		    printf("%s",(*in).c_str());
		}
		cout<<" ";
	    }
	    cout<<endl;
	}
   
	//--------------------------------------
    }

    vector<string> del(vector<string>v,int position){
	vector<string>word;
	int i=0;
	for(auto it=v.begin();it!=v.end();i++,it++){
	    if(i!=position){
		word.push_back(*it);
	    }
	}
	return word;
    }
    public:
    void start(){//查找算法

	//考虑到的情况：1。只有一个运算，结果存在MultiTmp1
	//2。两个运算，第一次运算存在MultiTmp1，第二个运算是~运算则直接~MultiTmp1，保存到MultiTmp2
	//                   再MultiTmp1=MultiTmp2,清空MultiTmp2
	//  第二个运算是|或者&时，将第三个词直接查询，结果存在MultiTmp2，再MultiTmp1和MultiTmp2运算
	//			保存到MultiTmp3，MultiTmp1=MultiTmp3，清空MultiTmp3
	//等等。。。。。


	int i=0;
	vector<int>MultiTmp1;//每次运算结果都保存到MultiTmp1
	vector<int>MultiTmp2;//好像是当出现(1&2)&(3|4)时,不记得了，各种情况出现推理都头大
	vector<int>MultiTmp3;//
	for(auto it=DealtWords.begin();it!=DealtWords.end();){
	    cout<<endl;
	    if((*it)=="|"||(*it)=="&"){
		if(0==i){
			if((*it)=="|"){
			    for(auto t1=MultiTmp1.begin();t1!=MultiTmp1.end();t1++){
				auto t2=MultiTmp2.begin();
				for(;t2!=MultiTmp2.end();t2++){
				    if(*t1==*t2)break;
				}
				if(t2==MultiTmp2.end())MultiTmp2.push_back(*t1);
			    }
			    MultiTmp1=MultiTmp2;
			}else{
			    for(auto t1=MultiTmp1.begin();t1!=MultiTmp1.end();t1++){
				for(auto t2=MultiTmp2.begin();t2!=MultiTmp2.end();t2++){
				    if(*t1==*t2){
					MultiTmp3.push_back(*t1);
					break;
				    }
				}
			    }
			    MultiTmp1=MultiTmp3;
			    MultiTmp3.erase(MultiTmp3.begin(),MultiTmp3.end());
			}
			MultiTmp2.erase(MultiTmp2.begin(),MultiTmp2.end());
			DealtWords=del(DealtWords,i);
			i=0;
			it=DealtWords.begin();
		}else{
		    if(i>1){
			FirstWord=getOneWord(DealtWords,i-2);
			SecondWord=getOneWord(DealtWords,i-1);
			if((*it)=="|"){
	//		    cout<<"empty |"<<endl;
			    OrQuery::SetFirstWord(FirstWord);
			    OrQuery::SetSecondWord(SecondWord);
			    OrQuery::Result();
			    if(MultiTmp1.empty()){
				MultiTmp1=OrQuery::getOrLine();
			    }else if(MultiTmp2.empty()){
				MultiTmp2=OrQuery::getOrLine();
			    }
			}else{
	//		    cout<<"empty &"<<endl;
			    AndQuery::SetFirstWord(FirstWord);
			    AndQuery::SetSecondWord(SecondWord);
			    AndQuery::Result();
			    if(MultiTmp1.empty()){
				MultiTmp1=AndQuery::getAndLine();
			    }else {
				if(MultiTmp2.empty()){
				    MultiTmp2=AndQuery::getAndLine();
				}
			    }
			}
			DealtWords=del(DealtWords,i-2);
			DealtWords=del(DealtWords,i-2);
			DealtWords=del(DealtWords,i-2);
			i=0;
			it=DealtWords.begin();
		    }else{
			FirstWord=getOneWord(DealtWords,i-1);
			DirectQuery::SetSearchWord(FirstWord);
			DirectQuery::Result();
			if((*it)=="|"){
	//		    cout<<"|"<<endl;
			    MultiTmp2=DirectQuery::getDirectLine();
			    for(auto in=MultiTmp2.begin();in!=MultiTmp2.end();in++){
				auto ii=MultiTmp1.begin();
				for(;ii!=MultiTmp1.end();ii++){
				    if(*in==*ii)break;
				}
				if(ii==MultiTmp1.end())MultiTmp1.push_back(*in);
			    }
			}else{
	//		    cout<<"&"<<endl;
			    MultiTmp2=DirectQuery::getDirectLine();
			    for(auto in=MultiTmp2.begin();in!=MultiTmp2.end();in++){
				auto ii=MultiTmp1.begin();
				for(;ii!=MultiTmp1.end();ii++){
				    if(*in==*ii){
					MultiTmp3.push_back(*in);
					break;
				    }
				}
			    }
			    MultiTmp1=MultiTmp3;
			    MultiTmp3.erase(MultiTmp3.begin(),MultiTmp3.end());
			}
			MultiTmp2.erase(MultiTmp2.begin(),MultiTmp2.end());
			DealtWords=del(DealtWords,i-1);
			DealtWords=del(DealtWords,i-1);
			i=0;
			it=DealtWords.begin();
		    }
		}
	    }else if((*it)=="~"){
		if(MultiTmp2.empty()){
		    if(MultiTmp1.empty()){
	//		cout<<"empty ~"<<endl;
			if(i>0){
			    FirstWord=getOneWord(DealtWords,i-1);
			    NotQuery::SetSearchWord(FirstWord);
			    NotQuery::Result();
			    MultiTmp1=NotQuery::getNotLine();
			    DealtWords=del(DealtWords,i-1);
			    DealtWords=del(DealtWords,i-1);
			}else{
			    NotQuery::Result(MultiLine);
			    MultiTmp1=NotQuery::getNotLine();
			    DealtWords=del(DealtWords,i);
			    MultiLine.erase(MultiLine.begin(),MultiLine.end());
			}
		    }else{
			if(i>0){
			    FirstWord=getOneWord(DealtWords,i-1);
			    NotQuery::SetSearchWord(FirstWord);
			    NotQuery::Result();
			    MultiTmp2=NotQuery::getNotLine();
			    DealtWords=del(DealtWords,i-1);
			    DealtWords=del(DealtWords,i-1);
			    
			}else{
			    NotQuery::Result(MultiTmp1);
			    MultiTmp1.erase(MultiTmp1.begin(),MultiTmp1.end());
			    MultiTmp1=NotQuery::getNotLine();
			    DealtWords=del(DealtWords,i);
			}
		    }
		}else{
		    NotQuery::Result(MultiTmp2);
		    MultiTmp2.erase(MultiTmp2.begin(),MultiTmp2.end());
		    MultiTmp2=NotQuery::getNotLine();
		    DealtWords=del(DealtWords,i);
		}
		i=0;
		it=DealtWords.begin();

	    }else{
		i++;
		it++;
	    }
	}
	if(!MultiTmp1.empty()){
	    if(MultiLine.empty()){
		MultiLine=MultiTmp1;
		MultiTmp1.erase(MultiTmp1.begin(),MultiTmp1.end());
	    }else{
		cout<<"MultiTmp1 and MultiLine not empty!";
		cout<<"It must be something wrong happened!"<<endl;
		MultiTmp1.erase(MultiTmp1.begin(),MultiTmp1.end());
		MultiLine.erase(MultiLine.begin(),MultiLine.end());
	    }
	}
	auto ii=DealtWords.begin();
	if(ii!=DealtWords.end()){
	    DirectQuery::SetSearchWord(*ii);
	    DirectQuery::Result();
	    MultiLine=DirectQuery::getDirectLine();
	    DealtWords=del(DealtWords,0);
	}
    }
};


int CheckInput(vector<string>word){//检查输入处理后得到的words是否可以正常查询
    int flag=0;
    if(1){
	auto it=word.begin();
	++it;
	if((it!=word.end())&&(*it=="|"||*it=="&")){
	    return -1;
	}
    }
    for(auto it=word.begin();it!=word.end();it++){
	if(it==word.begin()){
	    if(*it=="|"||*it=="&"||*it=="~"){
		return -1;
	    }
	}else{
	    if(1==flag){
		if(*it=="|"||*it=="&"){
		    return -1;
		}else{
		    flag=0;
		}
	    }else{
		if(*it=="|"||*it=="&"){
		    flag=1;
		}		
	    }
	}
    }
    return 0;//return 0 正常
}

void work(MultiQuery M){
    stack<int>a;//临时保存运算符到栈
    string s="";
    vector<string>words;
    string TempString;//保存一个词，放到words

    cout<<endl<<endl<<endl;
    cout<<"支持的符号有：非 ~  或 |  ";
    cout<<"与 &   (  ) "<<endl;
    cout<<"请输入查询内容：";
    getline(cin,s);
    
    while(s==""||s=="\n"){
	cin.clear();
	cin.sync();
	cout<<"请输入查询内容：";
	getline(cin,s);
    }

    //对要查询内容进行处理的算法
    for (int i=0;i<s.size();i++){
	if(s[i]==' ')continue;
	if(GetType(s[i])==2){//字符
	    TempString += s[i];
	}else if(GetType(s[i])==1){//运算符
	    if(!TempString.empty()){
		words.push_back(TempString);
		TempString="";
	    }
	    if(a.empty()||(GetLevel(s[i])>GetLevel(a.top()))){
		a.push(s[i]);
	    }else{
		while(!a.empty()&&(GetLevel(s[i])<=GetLevel(a.top()))){
		    TempString+=a.top();
		    words.push_back(TempString);
		    TempString="";
		    a.pop();
		}
		a.push(s[i]);
	    }
	}else if(GetType(s[i])==0){//括号
	    if(s[i]=='('){
		a.push(s[i]);
	    }else{
		if(!TempString.empty()){
		    words.push_back(TempString);
		    TempString="";
		}
		while(a.top()!='('){
		    TempString+=a.top();
		    words.push_back(TempString);
		    TempString="";
		    a.pop();
		}
		a.pop();
	    }
	}
    }
    if(!TempString.empty()){
	words.push_back(TempString);
	TempString="";
    }

    while(!a.empty()){
	TempString+=a.top();
	words.push_back(TempString);
	TempString="";
	a.pop();
    }
    //算法结束，保存到words里

    M.SetDealtWords(words);//根据words进行查询
//    M.ShowDealtWords();
    M.start();

    cout<<endl<<endl<<"查询内容：";
    cout<<s<<endl;
    if(0!=CheckInput(words)){//检查表达式是否有误
	cout<<"------输入有误-------"<<endl;
    }
    M.ShowResult();

}

int main()
{
    system("clear");
    string Input="";
    Input=TextExist();//输入要查询的文件并检查是否存在
    MultiQuery M(Input);
    Input="";
    work(M);//开始查询
    while(1){
	cout<<endl;
	cout<<endl;
	cout<<"继续查询？（y/n）";
	cin>>Input;
	getchar();//获取换行符
	if(Input=="n"){
	    break;
	}
	else {
	    Input="";
	    cout<<"更换查找的文件？(y/n)";
	    cin>>Input;
	    getchar();//获取换行符
	    if(Input=="y"){
		Input="";
		Input=TextExist();//输入要查询的文件并检查是否存在
		M.SetDestText(Input);//重置要查询的文件
	    }
	    work(M);//开始查询
	}
    }
    system("clear");
    return 0;
}
